<template>
  <div >
    <Row :gutter="10" class="margin-top-10">
      <card>
        <p slot="title">
          <Icon type="ios-list" />
          表单设计列表
        </p>
        <Row>
          <Input v-model="formNameQuery" placeholder="请输入表单名称..." style="width: 200px"/>
          <Input v-model="formCreateUserQuery" placeholder="请输入表单创建人..." style="width: 200px"/>
          <Button @click="handleRead" type="primary" icon="search">搜索</Button>
        </Row>
        <Row class="margin-top-10 searchable-table-con1">
          <div>
            <Table refs="formTemplate" border :columns="columns" :data="records" @on-row-click="handleRowClick" highlight-row></Table>
          </div>
        </Row>
        <Row class="margin-top-10 searchable-table-con1">
          <Page :total="totalCount" :page-size="size" show-total @on-change="changePage"></Page>
        </Row>
      </card>
    </Row>
    <Row :gutter="10" class="margin-top-10">
      <Col span="12">
      <Card >
        <Alert banner type="warning">
          <Icon type="compose" />
          <Poptip  trigger="hover" placement="top-start" content="请拖动设计器下的组件到右边的幕布完成表单的设计">
            设计器(请拖动设计器下的组件到右边的幕布完成表单的设计)
          </Poptip>
        </Alert>
        <Form :label-width="100" class="b-a">
          <draggable :clone="cloneData" :list="form_list" :options="dragOptions1">
            <transition-group class="form-list-group" type="transition" :name="'flip-list'" tag="div">
              <renders v-for="(element,index) in form_list" :key="index" :ele="element.ele" :obj="element.obj || {}">
              </renders>
            </transition-group>
          </draggable>
        </Form>
      </Card>
      </col>
      <Col span="12">
      <Card >
        <Form ref="formValidate" class="b-a" :label-width="100" :model="formData" @submit.native.prevent >
          <Row>
            <Col span="12"><Alert style="margin: 15px 15px 0;" type="warning" show-icon>(幕布)未绑定数据字典控件无效</Alert></Col>
            <Col span="12">
            <FormItem >
              <Button type="primary" style="margin: 15px 0px 0px -95px;" @click="handleSubmit()" >保存表单</Button>
              <Button   style="margin-top: 15px;margin-left: 5px" @click="handleReset()" >清空</Button>
            </FormItem>
            </Col>
          </Row>
          <draggable :list="sortable_item" :options="dragOptions2">
            <transition-group class="form-list-group" type="transition" :name="'flip-list'" tag="div" >
              <renders @handleRemoveEle="removeEle" @handleConfEle="confEle" @changeVisibility="changeVisibility" v-for="(element,index) in sortable_item" :key="index" :index="index" :ele="element.ele" :obj="element.obj || {}" :data="formData" @handleChangeVal="val => handleChangeVal(val,element)" :sortableItem="sortable_item" :config-icon="true">
              </renders>
            </transition-group>
          </draggable>
        </Form>
      </Card>
      </Col>
    </Row>
      <Modal v-model="showModal" :title="'配置' + modalFormData.modalTitle + '属性'" :mask-closable="false">
        <Form class="form_content" :label-width="100" :model="modalFormData" ref="modalFormData">
          <FormItem label="控件名称：" v-if="typeof modalFormData.label != 'undefined'" >
            <i-input v-model="modalFormData.label" @change.native="handleName" placeholder="请输入控件名称" :maxlength="6" ></i-input>
          </FormItem>
          <!--类型是select,radio,checkbox,cascader,button的组件可以选择数据字典-->
          <FormItem label="数据字典：" v-if="dictionaryTypes.indexOf(modalFormData.type) >= 0">
            <Select v-model="modalFormData.dict" filterable @on-change="handleDataDictChange">
              <!-- value绑定json字符串的原因是，需要用到parent_name，当handleDataDictChange触发，赋值到modalFormData -->
              <Option :disabled="dataDictSelected.indexOf(item.id) >= 0" v-for="item in dataDictList" :value="JSON.stringify({
                id: item.id, parent_name: item.parent_name})" :key="item.id">{{ item.label }}</Option>
            </Select>
          </FormItem>
          <!--非select,radio,checkbox,cascader利用翻译组件自动翻译name属性-->
          <FormItem label="name属性：" v-if="typeof modalFormData.name != 'undefined'">
            <i-input v-model="modalFormData.name" placeholder="" :disabled="nameDisabledTypes.indexOf(modalFormData.type) >= 0"></i-input>
          </FormItem>
          <FormItem label="关联数据：" v-if="typeof modalFormData.relation != 'undefined'">
            <!-- 当绑定name并且当前relationList存在数据时候才可以关联字段 -->
            <Checkbox :disabled="!modalFormData.name || !relationList.length" v-model="modalFormData.relation">是否关联字段</Checkbox>
          </FormItem>
          <FormItem label="关联配置：" v-if="typeof modalFormData.relation != 'undefined' && modalFormData.relation">
            <Select v-model="modalFormData.relation_name" class="inline-block" style="width: 150px" @on-change="_=>modalFormData.relation_value = ''">
              <Option :disabled="item.obj.name == modalFormData.name" v-for="(item,index) in relationList" :key="index" :value="item.obj.name">{{item.obj.label}}</Option>
            </Select>
            <p class="inline-block padder-sm">等于</p>
            <Select v-model="modalFormData.relation_value" class="inline-block" style="width: 150px">
              <Option v-for="(item,index) in relationValue" :key="index" :value="item.label_value">{{item.label_name}}</Option>
            </Select>
          </FormItem>
          <FormItem label="placeholder：" v-if="typeof modalFormData.placeholder != 'undefined'">
            <i-input v-model="modalFormData.placeholder" placeholder="请输入placeholder"></i-input>
          </FormItem>
          <FormItem label="最大长度：" v-if="typeof modalFormData.maxLength != 'undefined'">
            <InputNumber v-model="modalFormData.maxLength" placeholder="请输入文本限制最大长度">
            </InputNumber>
          </FormItem>
          <FormItem label="最大限制：" v-if="typeof modalFormData.maxSize != 'undefined'">
            <InputNumber :formatter="value => `${value}kb`" :parser="value => value.replace('kb', '')" v-model="modalFormData.maxSize" placeholder="请输入上传文件最大限制">
            </InputNumber>
          </FormItem>
          <FormItem label="上边距：" v-if="typeof modalFormData.marginTop != 'undefined'">
            <InputNumber :formatter="value => `${value}px`" :parser="value => value.replace('px', '')" v-model="modalFormData.marginTop" placeholder="请输入标签上边距">
            </InputNumber>
          </FormItem>
          <FormItem label="左边距：" v-if="typeof modalFormData.marginLeft != 'undefined'">
            <InputNumber :formatter="value => `${value}px`" :parser="value => value.replace('px', '')" v-model="modalFormData.marginLeft" placeholder="请输入标签左边距">
            </InputNumber>
          </FormItem>
          <FormItem label="下边距：" v-if="typeof modalFormData.marginBottom != 'undefined'">
            <InputNumber :formatter="value => `${value}px`" :parser="value => value.replace('px', '')" v-model="modalFormData.marginBottom" placeholder="请输入标签下边距">
            </InputNumber>
          </FormItem>
          <FormItem label="详细地址：" v-if="typeof modalFormData.details_address != 'undefined'">
            <Checkbox v-model="modalFormData.details_address">是否需要详细地址</Checkbox>
          </FormItem>
          <FormItem label="验证规则：" v-if="typeof modalFormData.rules != 'undefined'">
            <Checkbox v-model="modalFormData.rules.require">必填</Checkbox>
            <Checkbox v-model="modalFormData.rules.number">数字</Checkbox>
            <Checkbox v-model="modalFormData.rules.positive">正整数</Checkbox>
            <Checkbox v-model="modalFormData.rules.phone">手机</Checkbox>
            <Checkbox v-model="modalFormData.rules.email">邮件</Checkbox>
            <Checkbox v-model="modalFormData.rules.idcard">身份证</Checkbox>
          </FormItem>
          <FormItem label="校验错误：" v-if="typeof modalFormData.ruleError != 'undefined'">
            <i-input v-model="modalFormData.ruleError" placeholder="请输入校验错误提示"></i-input>
          </FormItem>
          <FormItem label="是否多选：" v-if="typeof modalFormData.multiple != 'undefined' && modalFormData.type != 'address'">
            <Checkbox v-model="modalFormData.multiple">多选</Checkbox>
          </FormItem>
          <FormItem label="仅支持图片：" v-if="typeof modalFormData.image != 'undefined'">
            <Checkbox v-model="modalFormData.image">是</Checkbox>
          </FormItem>
          <FormItem label="时间格式：" v-if="typeof modalFormData.format != 'undefined'">
            <RadioGroup v-model="modalFormData.format">
              <Radio label="yyyy年MM月dd日"></Radio>
              <Radio label="yyyy-MM-dd HH:mm"></Radio>
            </RadioGroup>
          </FormItem>
          <FormItem label="行内元素：" v-if="typeof modalFormData.inlineBlock != 'undefined'">
            <Checkbox v-model="modalFormData.inlineBlock">是</Checkbox>
          </FormItem>
          <FormItem label="显示行数：" v-if="typeof modalFormData.maxRows != 'undefined'">
            <Slider v-model="modalFormData.maxRows" :min="2" :max="10"></Slider>
          </FormItem>
          <FormItem label="标题大小：" v-if="typeof modalFormData.level != 'undefined'">
            <InputNumber :max="6" :min="1" v-model="modalFormData.level"></InputNumber>
          </FormItem>
          <FormItem label="字体颜色：" v-if="typeof modalFormData.color != 'undefined'">
            <ColorPicker v-model="modalFormData.color" />
          </FormItem>
        </Form>
        <div slot="footer">
          <Button type="text" @click="handleCancel">取消</Button>
          <Button type="primary" :loading="modalFormData.loading" @click="handleOk">确定</Button>
        </div>
      </Modal>
  </div>
</template>
<script>
import draggable from "vuedraggable";
import form_list from "./custom_form/FormList";
import api from "../../../libs/api"
import util from "../../../libs/util"
export default {
  components: {
      draggable
  },
  data() {
    return {
        //表单列表
        records:[],  //表单列表
        totalCount:0,//表单列表总页数
        current: 1,//当前页
        size: 10,//页面大小
        totalPage: 0, //总条数
        formNameQuery:"",//表单名称
        formCreateUserQuery:"", //表单创建人
        columns: [
            {
                title: '表单名称',
                key: 'formName'
            },
            {
                title: '表单创建人',
                key: 'createUserView'
            },
            {
                title: '状态',
                key: 'statusView'
            },
            {
                title: '创建时间',
                key: 'createTime'
            },
            {
                title: '更新时间',
                key: 'updateTime'
            }, {
                title: '操作',
                key: 'action',
                width: 240,
                align: 'center',
                render: (h, params) => {
                    let self=this;
                    if(!util.isBlank(params.row.tableName))
                      return h('div', [
                        h('Button', {
                            props: {
                                type: 'warning',
                                size: 'small'
                            },
                            style: {
                                marginRight: '5px'
                            },
                            on: {
                                click: (event) => {
                                    self.$post(api.formTemplates.structure.replace("{templateId}",params.row.id),{});
                                    event.stopPropagation(); //阻止事件冒泡
                                }
                            }
                        }, '同步表结构')]);
                }
            }
        ],
        //表单设计器数据
        form_list: form_list,
        sortable_item: [],
        showModal: false,
        dictionaryTypes:['select','radio','checkbox','cascader','button'],
        nameDisabledTypes:['select','radio','checkbox','title','p','hr'],  //数据字典组件类型
        commonTypes:['select','radio','checkbox'], //后台为表单类型
        interfaceTypes:['cascader','button'], //后台为接口类型
        // 深拷贝对象，防止默认空对象被更改
        // 颜色选择器bug，对象下color不更新
        modalFormData: {
          color: '',
          loading: false
        },
        formData: {},
        dataDict: [],
        formName:"",  //表单名称
        formTemplateId:"",  //表单模板Id
      };
  },
  methods: {
      //读取列表数据
      handleRead(){
          let data = {};
          data.current = this.current;
          data.size = this.size;
          data.formNameQuery=this.formNameQuery;
          data.formCreateUserQuery=this.formCreateUserQuery;
          this.$get(api.formTemplates.base, data).then(response => {
              this.totalPage = this.util.calTotalPage(response.obj.total, this.size);
              this.totalCount = response.obj.total;
              this.records = [];
              for (let i in response.obj.records) {
                  this.records.push(response.obj.records[i])
              }
          });
      },
      //表单列表点击事件
      handleRowClick(row,index){
          let self=this;
          //实时数据
          this.$get(api.formTemplates.base+"/"+row.id).then(response=>{
              if(200==response.code){
                  self.sortable_item = JSON.parse( response.obj.formTemplate || '[]');
                  self.formTemplateId=response.obj.id;
                  self.formName=response.obj.formName;
              }
          })

      },
      //翻页
      changePage(index){
          this.current = index;
          this.handleRead();
      },
      //翻译name属性
      handleName(event){
          let self=this;
          typeof this.modalFormData.type!="undefined"&&this.nameDisabledTypes.indexOf(this.modalFormData.type) <0&&event.target.value!=""&&this.$get(api.formTemplates.translate,{text:event.target.value}).then((response)=>{
             if(200==response.code){
                 self.modalFormData.name=response.obj;
             }else{

             }
          });
      },

      // 克隆表单提交事件
      handleSubmit() {
        let self=this;
        //缓存表单过滤没有设置name属性的元素
        localStorage.setItem('template_form', JSON.stringify(self.sortable_item.filter(v => {
          return !!v.obj.name
        })));
       this.$Modal.confirm({
            loading:true,
            render: (h) => {
                return h('Input', {
                    props: {
                        value: self.formName,
                        autofocus: true,
                        placeholder: '请输入表单名称'
                    },
                    on: {
                        input: (val) => {
                            self.formName = val;
                        }
                    }
                })
            },
           onOk: function() {
               let modal = this;
               modal.$data.buttonLoading = false;
               //验证表单
               if(self.formName==""){
                   self.$Message.error('表单名称不允许为空',3);
                   return false;
               }
               let formTemplate=localStorage.getItem('template_form').toString();
               if("[]"==formTemplate){
                   self.$Message.error('表单未包含任何组件元素',3);
                   return false;
               }
               //保存表单数据
               let data={};
               data.formTemplate=formTemplate;
               data.formName=self.formName;
               if(""==self.formTemplateId){  //保存表单
                   self.$post(api.formTemplates.base,data).then(response=>{
                       if(200==response.code){
                           self.handleReset();
                           modal.remove();
                       }
                   });
               }else{
                   self.$put(api.formTemplates.base+"/"+self.formTemplateId,data).then(response=>{
                       if(200==response.code){
                          self.handleReset();
                          modal.remove();
                       }
                   });
               }

              }
          });
      },
      // 清空克隆表单
      handleReset() {
        this.sortable_item = [];
        this.formName="";
        this.formTemplateId="";
      },
      // modal内数据字典选项发生改变触发事件
      handleDataDictChange(val) {
        let self=this;
        // 选中后，val默认赋值到modalFormData.dict
        const obj = JSON.parse(val);
        // 数据加载中，禁止modal_submit提交按钮
        self.$set(self.modalFormData, 'loading', true);
        //从后台读取数据字典
        if(self.interfaceTypes.indexOf(self.modalFormData.type)>-1){
            self.$get(api.formTemplates.dictionary.interface+"/"+obj.id).then(response => {
                if(response.obj!=null){ //得到接口资源的数据字典
                    if("cascader"==self.modalFormData.type){
                        self.$get(api.baseURL+response.obj.url).then(resp=>{
                            if(200==resp.code&&resp.obj!=null){
                                self.modalFormData = Object.assign({}, self.modalFormData, {
                                    loading: false,
                                    items: {},
                                    data:resp.obj,
                                    parent_name: obj.parent_name
                                });
                            }
                        });
                    }else if("button"==self.modalFormData.type){
                        self.modalFormData = Object.assign({}, self.modalFormData, {
                            loading: false,
                            items: {},
                            value:response.obj.url
                          });
                    }
                }
            });
        }else{
            self.$get(api.formTemplates.dictionary.form+"/"+obj.id).then(response => {
                let items=[];
                response.obj.childrensView.forEach(function (children) {
                    let item={};
                    item.label_value=children.dictionaryValue;
                    item.label_name=children.name;
                    items.push(item);
                });
                self.modalFormData = Object.assign({}, self.modalFormData, {
                    name:response.obj.dictionaryValue,
                    loading: false,
                    items: items,
                    parent_name: obj.parent_name
                });
            });
        }

      },
      // 控件回填数据
      handleChangeVal(val, element) {
        this.$set(this.formData, element.obj.name, val);
      },
      // https://github.com/SortableJS/Vue.Draggable#clone
      // 克隆,深拷贝对象
      cloneData(original) {
        // 添加一个modal标题
        original.obj.modalTitle = original.obj.label || "";
        // 深拷贝对象，防止默认空对象被更改
        return JSON.parse(JSON.stringify(original));
      },
      // modal点击确定执行事件
      handleOk() {
        const index = this.modalFormData.listIndex;
        this.sortable_item[index].obj = Object.assign({},
          this.sortable_item[index].obj,
          this.modalFormData
        );
        this.handleCancel();
      },
      // modal点击取消执行事件，清空当前modal内容
      handleCancel() {
        this.showModal = false;
        setTimeout(_ => {
          this.modalFormData = {
            color: '',
            loading: false
          };
        }, 500)
      },
      // 显示modal,配置被克隆控件
      confEle(index) {
        const list_temp = Object.assign({}, this.sortable_item[index]);
        for (let i in list_temp.obj) {
          this.modalFormData[i] = list_temp.obj[i];
        }
        // 配置项中未找到color，删除modalFormData中自带color属性
        if (!list_temp.obj['color']) delete this.modalFormData.color;
        // 设置被配置控件的index，便于完成配置找到相应对象赋值
        this.modalFormData.listIndex = index;
        // Vue 不能检测到对象属性的添加或删除
        this.modalFormData = Object.assign({}, this.modalFormData);
        this.showModal = true;
      },
      // 删除克隆控件
      removeEle(index) {
        let name = this.sortable_item[index].obj.name;
        this.sortable_item.splice(index, 1);
        if (!name) return;
        for (let i in this.sortable_item) {
          // 当relation为true并且关联字段被确认
          if (this.sortable_item[i].obj.relation && this.sortable_item[i].obj.relation_name === name) {
            this.$set(this.sortable_item[i].obj, "relation", false);
            this.$set(this.sortable_item[i].obj, "relation_name", "");
            this.$set(this.sortable_item[i].obj, "relation_value", "");
            break;
          }
        }
      },
      // 更改当前渲染字段是否显示
      changeVisibility(index, visibility) {
        this.$set(this.sortable_item[index].obj, 'visibility', visibility);
      }

    },
    watch: {
      showModal(val) {
        if (!val) {
          this.handleCancel();
        }
      }
    },
    computed: {
      // 数据字典已选择项
      dataDictSelected() {
        return this.sortable_item.map(v => {
          const obj = JSON.parse(v.obj.dict || '{}');
          return obj.id || -1;
        })
      },
      // 对应控件的数据字典
      dataDictList() {
        /* 后台数据字典'select','radio','checkbox',同为Form类型而'cascader','button'组件为接口类型，过滤时需要处理下*/
         let self=this;
         return this.dataDict.filter(v => {
            return v.type == (self.commonTypes.indexOf(this.modalFormData.type)>=0?"Form":"Interface");
         })
      },
      // 拖拽表单1
      dragOptions1() {
        return {
          animation: 0,
          ghostClass: "ghost",
          // 分组
          group: {
            name: "shared",
            pull: "clone",
            revertClone: false
          },
          // 禁止拖动排序
          sort: false
        };
      },
      // 拖拽表单2
      dragOptions2() {
        return {
          animation: 0,
          ghostClass: "ghost",
          group: {
            // 只允许放置shared的控件,禁止pull
            put: ["shared"]
          }
        };
      },
      // 被关联字段列表
      relationList() {
        // 只有type内三项可作为被关联字段
        let type = ['select', 'radio', 'checkbox'];
        const arr = this.sortable_item.filter(k => {
          return type.indexOf(k.ele) >= 0 && !!k.obj.name;
        })
        return arr;
      },
      // 被关联字段数据
      relationValue() {
        const name = this.modalFormData.relation_name;
        let items = [];
        if (!name) return items;
        for (let i in this.sortable_item) {
          if (this.sortable_item[i].obj.name == name) {
            items = this.sortable_item[i].obj.items;
          }
        }
        return items;
      }
  },
  mounted(){
      //为了防止火狐浏览器拖拽的时候以新标签打开，此代码真实有效
      document.body.ondrop = function (event) {
          event.preventDefault();
          event.stopPropagation();
      }
  },
  created() {
      let self=this;
      self.$get(api.formTemplates.dictionary.base).then(response=>{
       if(response.obj!=null){
            let data=response.obj;
            data.forEach(function (dictionary) {
                dictionary.label=dictionary.name;
//                dictionary.type=("Form"==dictionary.type?"select":"cascader");
                dictionary.parent_name=null;
            });
            self.dataDict=data;
       }
     });
      //读取列表数据
      self.handleRead();

//    this.sortable_item = JSON.parse(localStorage.getItem('template_form') || '[]');

  }
};
</script>
<style>
.inline {
  display: inline-block;
}

.m-l-lg {
  margin-left: 30px
}

.wrapper {
  padding: 15px
}

.inline-block {
  display: inline-block;
}

.padder-sm {
  padding-right: 10px;
  padding-left: 10px
}

.b-a {
  border: 1px solid #ccc;
  height: 100% !important;
}


.ghost {
  opacity: 0.5;
  background: #c8ebfb;
}

.form-list-group {
  min-height: 200px;
  padding: 20px !important;
}

/* 设置items下所有鼠标样式为 move */

.items,
.items * {
  cursor: move;
}

/* 配置按钮默认位置 */

/* 例如P Hr Title按钮 */

.items .item-icon {
  transition: all 2s ease;
  position: absolute;
  top: -18px;
  right: 0px;
  opacity: 0;
  max-height: 0;
  overflow: hidden;
}

/* form控件下配置按钮位置 */

.ivu-form-item.items .item-icon {
  top: -25px;
}

/* 配置按钮样式 */

.item-icon i {
  cursor: pointer !important;
  margin-right: 5px;
}

.items:hover .item-icon {
  transition: inherit;
  opacity: 1;
  max-height: 50px;
}

/* 提交按钮下方无 margin-bottom */

.form_content .ivu-form-item:last-child {
  margin-bottom: 0;
}


/* 表单校验选项样式 */

.ivu-form-item-required .ivu-form-item-label:before {
  content: '';
}

.items.sortable-items-required .ivu-form-item-label:before {
  content: '*';
  display: inline-block;
  margin-right: 4px;
  line-height: 1;
  font-family: SimSun;
  font-size: 12px;
  color: #ed3f14;
}
</style>